package crmdna.contactdetail;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import crmdna.common.APIException;
import crmdna.common.APIResponse.Status;
import crmdna.common.Utils;
import crmdna.group.Group;

public class ContactDetail {
	public enum Gender {
		MALE, FEMALE
	}

	public static Gender getGender(String gender) {

		if (null == gender)
			return null;

		gender = gender.toUpperCase();
		if (gender.equals("M") || gender.equals("MALE") || gender.equals("MAN"))
			return Gender.MALE;

		if (gender.equals("F") || gender.equals("FEMALE")
				|| gender.equals("WOMAN"))
			return Gender.FEMALE;

		Logger logger = Logger.getLogger(ContactDetail.class.getName());
		logger.warning("Invalid gender [" + gender + "]");
		return null;
	}

	public static  List<ContactDetailProp> sanitizeAndEnsureValid(
			String client, List<ContactDetailProp> contacts) {

		Set<Long> allGroupIds = Group.getAllGroupIds(client);

		for (int i = 0; i < contacts.size(); i++) {
			ContactDetailProp c = contacts.get(i);

			//throw error if first name is not specified
			if ((c.firstName == null) || c.firstName.equals(""))
				throw new APIException(
						Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
						"Error in record no [" + (i + 1)
								+ "]: First name is missing");
			
			c.homePhone = Utils.sanitizePhoneNo(c.homePhone);
			c.officePhone = Utils.sanitizePhoneNo(c.officePhone);
			c.mobilePhone = Utils.sanitizePhoneNo(c.mobilePhone);
			
			//email and phone numbers if specified should be valid
			
			//at least email or 1 contact number should be specified
			
			boolean emailOrPhoneNoValid = false;
			if (c.email != null) {
				if (Utils.isValidEmailAddress(c.email)) {
					emailOrPhoneNoValid = true;
				} else {
					throw new APIException(
							Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
							"Error in record no ["
									+ (i + 1)
									+ "]: Email [" + c.email + "] is not valid");

				}
			}
			
			if (c.homePhone != null) {
				if (Utils.isValidPhoneNumber(c.homePhone)) {
					emailOrPhoneNoValid = true;
				} else {
					throw new APIException(
							Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
							"Error in record no ["
									+ (i + 1)
									+ "]: Home phone [" + c.homePhone + "] is not valid");

				}
			}
			
			if (c.mobilePhone != null) {
				if (Utils.isValidPhoneNumber(c.mobilePhone)) {
					emailOrPhoneNoValid = true;
				} else {
					throw new APIException(
							Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
							"Error in record no ["
									+ (i + 1)
									+ "]: Mobile phone [" + c.mobilePhone + "] is not valid");

				}
			}
			
			if (c.officePhone != null) {
				if (Utils.isValidPhoneNumber(c.officePhone)) {
					emailOrPhoneNoValid = true;
				} else {
					throw new APIException(
							Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
							"Error in record no ["
									+ (i + 1)
									+ "]: Mobile phone [" + c.officePhone + "] is not valid");

				}
			}			

			if (! emailOrPhoneNoValid)
				throw new APIException(
						Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
						"Error in record no ["
								+ (i + 1)
								+ "]: Email or atleast one contact phone number should be valid. "
								+ "Phone number should start with +. Eg: +659867364");

			if (c.centerId == null) 
				throw new APIException(
						Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
						"Error in record no ["
								+ (i + 1)
								+ "]: Group or center not specified");
			
			if (!allGroupIds.contains(c.centerId)) {
				throw new APIException(Status.ERROR_RESOURCE_DOES_NOT_EXIST,
						"Error in record no [" + (i + 1)
								+ "]: There is no center with centerId ["
								+ c.centerId + "]");
			}						
		}
		
		return contacts;
	}

	public static void ensureNameContactEmailOrPhoneAndGroupSpecified(
			String client, ContactDetailProp contact) {

		List<ContactDetailProp> contacts = new ArrayList<>();
		contacts.add(contact);
		sanitizeAndEnsureValid(client, contacts);
	}

	public static void ensureEmailOrPhoneNumberValid(ContactDetailProp contact) {

		if (contact.email != null)
			Utils.ensureValidEmail(contact.email);

		if (null != contact.homePhone)
			Utils.ensureValidPhoneNumber(contact.homePhone);

		if (null != contact.mobilePhone)
			Utils.ensureValidPhoneNumber(contact.mobilePhone);

		if (null != contact.officePhone)
			Utils.ensureValidPhoneNumber(contact.officePhone);

		// email or one of the phone numbers should be specified
		if ((contact.email == null) && (contact.mobilePhone == null)
				&& (contact.homePhone == null) && (contact.officePhone == null)) {
			throw new APIException(Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
					"Either email or one of the phone numbers should be specified");
		}
	}

	public static void ensureFirstNameAndValidEmailSpecified(
			ContactDetailProp contact) {

		if ((contact.firstName == null) || (contact.firstName.equals("")))
			throw new APIException(Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
					"First name not specified");

		if ((contact.email == null) || (contact.email.equals("")))
			throw new APIException(Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
					"Email not specified");

		Utils.ensureValidEmail(contact.email);
	}

	public static List<ContactDetailProp> getContactDetailsFromListOfMap(
			List<Map<String, String>> listOfMap) {

		List<ContactDetailProp> contactDetailProps = new ArrayList<>();

		if (listOfMap == null)
			return contactDetailProps;

		for (Map<String, String> map : listOfMap) {
			ContactDetailProp contactDetailProp = getContactDetailFromMap(map);
			contactDetailProps.add(contactDetailProp);
		}

		return contactDetailProps;
	}

	static ContactDetailProp getContactDetailFromMap(Map<String, String> map) {
		if (map == null)
			return null;

		ContactDetailProp contactDetailProp = new ContactDetailProp();

		for (String key : map.keySet()) {
			key = key.toLowerCase();
			String value = map.get(key);

			if (key.equals("email"))
				contactDetailProp.email = value;
			else if (key.equals("firstname"))
				contactDetailProp.firstName = value;
			else if (key.equals("lastname"))
				contactDetailProp.lastName = value;
			else if (key.equals("nickname"))
				contactDetailProp.nickName = value;
			else if (key.equals("homephone")) {		
				value = Utils.sanitizePhoneNo(value);
				contactDetailProp.homePhone = value;								
			}
			else if (key.equals("officephone")) {
				value = Utils.sanitizePhoneNo(value);
				contactDetailProp.officePhone = value;
			}
			else if (key.equals("mobilephone")) {
				value = Utils.sanitizePhoneNo(value);
				contactDetailProp.mobilePhone = value;
			}
			else if (key.equals("gender"))
				contactDetailProp.gender = getGender(value);
			else if (key.equals("city"))
				contactDetailProp.city = value;
			else if (key.equals("country"))
				contactDetailProp.country = value;
			else if (key.equals("homeaddress"))
				contactDetailProp.homeAddress = value;
			else if (key.equals("officeaddress"))
				contactDetailProp.officeAddress = value;
		}

		return contactDetailProp;
	}

	public static String getCSV(List<ContactDetailProp> contactDetailProps) {
		if (contactDetailProps == null)
			return null;

		StringBuilder builder = new StringBuilder();
		builder.append("First Name,Last Name,Email,Gender,Mobile Phone,Home Phone,Office Phone,City,Country,Pincode");
		builder.append("\n");

		for (ContactDetailProp c : contactDetailProps) {
			builder.append(getCSV(c)).append("\n");
		}

		return builder.toString();
	}

	private static String getCSV(ContactDetailProp c) {
		if (null == c)
			return null;

		String gender = null;
		if (c.gender != null)
			gender = c.gender.toString();

		StringBuilder builder = new StringBuilder();
		builder.append(Utils.csvEncode(c.firstName)).append(",")
				.append(Utils.csvEncode(c.lastName)).append(",")
				.append(Utils.csvEncode(c.email)).append(",")
				.append(Utils.csvEncode(gender)).append(",")
				.append(Utils.csvEncode(c.mobilePhone)).append(",")
				.append(Utils.csvEncode(c.homePhone)).append(",")
				.append(Utils.csvEncode(c.officePhone)).append(",")
				.append(Utils.csvEncode(c.city)).append(",")
				.append(Utils.csvEncode(c.country));

		return builder.toString();
	}
}
